<?php

namespace support\core;

use Closure;
use support\exception\ExceptionHandler;

class Pipeline
{
    protected $pipes = [];
    protected $passable;

    public function push($pipes)
    {
        $this->pipes = is_array($pipes) ? $pipes : [$pipes];
        return $this;
    }

    public function send($passable)
    {
        $this->passable = $passable;
        return $this;
    }

    public function then(Closure $destination)
    {
        $pipeline = array_reduce(
            array_reverse($this->pipes),
            $this->carray(),
            function ($passable) use ($destination) {
                try {
                    return $destination($passable);
                } catch (\Throwable $e) {
                    $exceptionHandler = app(ExceptionHandler::class);
                    $exceptionHandler->report();
                    return $exceptionHandler->render($passable, $e);
                }
            }
        );
        return $pipeline($this->passable);
    }

    public function carray()
    {
        return function ($stack, $pipe) {
            return function ($passable) use ($stack, $pipe) {
                try {
                    return $pipe($passable, $stack);
                } catch (\Throwable $e) {
                    $exceptionHandler = app(ExceptionHandler::class);
                    $exceptionHandler->report();
                    return $exceptionHandler->report($passable, $e);
                }
            };
        };
    }
}
